/*
 * anima/x86_64/space.hh - x86-64-specific address space interface.
 * Copyright (C) 2007  Mikhail Vorozhtsov
 * See the LICENSE section of the README file for details.
 */

/* $Id$ */

#ifndef HEADER_ANIMA_X86_64_SPACE_HH
#define HEADER_ANIMA_X86_64_SPACE_HH

#include HEADER (anima/x86_64,pdpm.hh)
#include HEADER (anima,pdb.hh)
#include HEADER (elf,elf.hh)

START_NAMESPACE (anima)

struct space_t;

END_NAMESPACE

START_NAMESPACE2 (anima,x86_64)

struct cpu_t;

struct space_t
{
  friend class ::anima::mm;
  friend class ::anima::cpu_t;
  friend class ANIMA_ARCH::cpu_t;

public:
  static const elf::hdr_t::data_t ELF_DATA = elf::hdr_t::DATA_2LSB;
  static const elf::hdr_t::os_abi_t ELF_OS_ABI = elf::hdr_t::OS_ABI_SYSV;
  static const elf::hdr_t::machine_t ELF_MACHINE = elf::hdr_t::MACHINE_X86_64;

public:
  static const u64_t START = TB (1);
  static const u64_t END = TB (2);

protected:
  struct allocator_t
  {
  private:
    ::anima::space_t *space;

  public:
    INLINE
    void
    init (::anima::space_t *space)
    {
      this->space = space;
    }

  public:
    INLINE
    bool
    use_first_page_p ()
    {
      return true;
    }

  public:
    void install (::x86_64::pe_t pml4e);

  public:
    mm::tte_t *map (u64_t paddr);
    void unmap ();

  public:
    ::anima::pdb::lvl1e_t *allocate ();
    void deallocate (::anima::pdb::lvl1e_t *lvl1e);
  };

  struct mapper_t
  {
  private:
    ::anima::space_t *space;

  public:
    INLINE
    void
    init (::anima::space_t *space)
    {
      this->space = space;
    }

  public:
    mm::tte_t *map (u64_t addr);
    void unmap (mm::tte_t *pte);
  };

protected:
  allocator_t maps_allocator;
  mapper_t mapper;

protected:
  self_pdpm_t<TB (1) - KB (4), TB (1) - GB (1), TB (1) - GB (2),
            allocator_t, false> maps_pdpm;
  ext_pdpm_t<TB (1) - KB (8), TB (1) - GB (1) + MB (2), TB (1) - GB (3),
             mapper_t, false> first_pdpm;
  ext_pdpm_t<TB (1) - KB (12), TB (1) - GB (1) + MB (4), TB (1) - GB (4),
             mapper_t, false> second_pdpm;

protected:
  ::x86_64::pe_t maps_pml4e;
  ::x86_64::pe_t first_pml4e;
  ::x86_64::pe_t second_pml4e;

protected:
  ::x86_64::pe_t iopb0_pte;
  ::x86_64::pe_t iopb1_pte;
};

END_NAMESPACE2

#endif /* HEADER_ANIMA_X86_64_SPACE_HH */

